Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | import {
ActionIcon,
Badge,
Box,
Group,
Image,
Text,
Title,
} from '@mantine/core';
import {
IconChefHat,
IconClock,
IconEdit,
IconFlame,
IconUsers,
} from '@tabler/icons-react';
import type { Route } from 'next';
import Link from 'next/link';
import { useTranslations } from 'next-intl';
import { FavoriteButton } from '@/components/buttons/FavoriteButton';
import classes from '../RecipeDetail.module.css';
import type { RecipeHeroProps } from '../types';
import { getDifficultyColor } from '../utils';
export const RecipeHero = ({ recipe, isOwner }: Readonly<RecipeHeroProps>) => {
const translate = useTranslations('recipeDetail');
const translateMisc = useTranslations('misc');
return (
<Box className={classes.hero}>
{recipe.imgSrc ? (
<Image
src={recipe.imgSrc}
alt={recipe.title}
className={classes.heroImage}
/>
) : (
<Box className={classes.heroPlaceholder}>
<IconChefHat size={80} color="var(--mantine-color-pink-4)" />
</Box>
)}
<Box className={classes.heroOverlay} />
{/* Top-right actions */}
<Group className={classes.heroActions} gap="xs">
<FavoriteButton
recipeId={recipe.id}
isFavorite={recipe.isFavorite ?? false}
size="lg"
/>
{isOwner && (
<ActionIcon
component={Link}
href={`/recipes/${recipe.id}/edit` as Route}
variant="subtle"
color="white"
size="lg"
>
<IconEdit size={22} />
</ActionIcon>
)}
</Group>
{/* Hero content */}
<Box className={classes.heroContent}>
<Title order={1} className={classes.heroTitle}>
{recipe.title}
</Title>
{recipe.description && (
<Text className={classes.heroDescription} mt={6}>
{recipe.description}
</Text>
)}
{/* Label pills */}
<Group gap="xs" mt="sm">
<Badge variant="light" className={classes.labelPill}>
{translateMisc(`category-${recipe.category.key}`)}
</Badge>
<Badge
variant="light"
color={getDifficultyColor(recipe.difficultyLevel.key)}
className={classes.labelPill}
>
{translateMisc(`level-${recipe.difficultyLevel.key}`)}
</Badge>
{recipe.labels.map((label) => (
<Badge
key={label.key}
variant="filled"
color="pink"
className={classes.labelPill}
>
{translateMisc(`label-${label.key}`)}
</Badge>
))}
</Group>
{/* Quick info pills */}
<Box className={classes.quickInfo}>
<span className={classes.infoPill}>
<IconClock size={16} />
{translate('cookingTime', { time: recipe.cookingTime })}
</span>
<span className={classes.infoPill}>
<IconUsers size={16} />
{translate('servingsCount', { count: recipe.servings })}
</span>
{recipe.ratingsCount > 0 && (
<span className={classes.infoPill}>
<IconFlame size={16} />
{recipe.averageRating.toFixed(1)} ({recipe.ratingsCount})
</span>
)}
</Box>
</Box>
</Box>
);
};
|